package com.knife.oauth.tenant.aspect;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;

import java.lang.reflect.Parameter;
import java.util.Objects;

/**
 * @author tianhao.luo@hand-china.com
 * @version 1.0
 * @date 2022年02月15日 星期二 11:45 上午
 * @description 2022-02-18 18:29:48.275 [main] INFO  o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'knifeTenantPointcut' of type [com.knife.tenant.aspect.KnifeTenantPointcut] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
 * 2022-02-18 18:29:48.303 [main] INFO  o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'knifeTenantAdvice' of type [com.knife.tenant.aspect.KnifeTenantAdvice] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
 * 2022-02-18 18:29:48.307 [main] INFO  o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'knifeTenantAdvisor' of type [com.knife.tenant.aspect.KnifeTenantAdvisor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
 * 2022-02-18 18:29:48.310 [main] INFO  o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'knifeInterfaceLogPointcut' of type [com.knife.interfaces.aspect.KnifeInterfaceLogPointcut] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
 * 2022-02-18 18:29:48.313 [main] INFO  o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'knifeInterfaceLogAdvice' of type [com.knife.interfaces.aspect.KnifeInterfaceLogAdvice] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
 * 2022-02-18 18:29:48.314 [main] INFO  o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'knifeInterfaceLogAdvisor' of type [com.knife.interfaces.aspect.KnifeInterfaceLogAdvisor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
 * 2022-02-18 18:29:48.315 [main] INFO  o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'knifeMethodLogAdvice' of type [com.knife.interfaces.aspect.KnifeMethodLogAdvice] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
 * 2022-02-18 18:29:48.316 [main] INFO  o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'knifeMethodLogPointcut' of type [com.knife.interfaces.aspect.KnifeMethodLogPointcut] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
 * 2022-02-18 18:29:48.317 [main] INFO  o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'knifeMethodLogAdvisor' of type [com.knife.interfaces.aspect.KnifeMethodLogAdvisor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
 * 日志中出现的这种提示表示，PersistenceExceptionTranslationPostProcessor和FilteredMethodValidationPostProcessor这两个实现了BeanPostProcessor的bean在注入的时候，发现日志中提示出现的类没有被代理；
 * 实际上日志中出现的类不需要关注是否被代理，这三个类组合起来可以实现类似代理的操作
 * @since 1.0
 */
@Component
@Order(-100)
public class KnifeTenantAdvice implements MethodInterceptor {

    private static final ThreadLocal<Long> org = ThreadLocal.withInitial(() -> 0L);

    public static final String ORGANIZATION_ID = "organizationId";

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        try {
            Parameter[] parameters = invocation.getMethod().getParameters();
            // 不存在参数,则不进行设置租户 id
            if (Objects.isNull(parameters)){
                return invocation.proceed();
            }
            Object[] arguments = invocation.getArguments();
            for (int i = 0; i < parameters.length; i++) {
                PathVariable pathVariable = parameters[i].getAnnotation(PathVariable.class);
                if ( (pathVariable != null && pathVariable.name().equals(ORGANIZATION_ID))){
                    String s = arguments[i].toString();
                    org.set(Long.parseLong(s));
                    break;
                }else if (parameters[i].getName().equals(ORGANIZATION_ID)){
                    String s = arguments[i].toString();
                    org.set(Long.parseLong(s));
                    break;
                }
            }
            return invocation.proceed();
        } finally {
            org.remove();
        }
    }

    /**
     * @description
     * @since 1.0
     * @version 1.0
     * @author tianhao.luo@hand-china.com
     * @date 2022/2/15 1:07 下午
     * @return url 上的租户 id
     */
    public static Long getTenantId(){
        return org.get();
    }
}
